package com.calvin.study.multithread.threadutils;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadPoolExecutor;

import com.calvin.study.utils.ThreadUtil;

public class CyclicBarrierDemo02 {

	static ThreadPoolExecutor threadPool = ThreadUtil.getMixedTargetThreadPool();

	public static void main(String[] args) {
		// pubg();
		// reset();
		interrput();
	}

	// 吃鸡
	private static void pubg() {
		// 凑够10人 开始游戏
		CyclicBarrier cb = new CyclicBarrier(10, () -> System.out.println("飞机马上就要起飞，请特种兵准备！"));

		for (int i = 0; i < 10; i++) {
			int finalI = i;
			threadPool.execute(() -> {
				try {
					Double rTime = 2000 * new Random().nextDouble();
					ThreadUtil.sleepMilliSeconds(rTime.intValue());
					System.out.println("玩家 " + finalI + " 进入房间进行等待... (" + cb.getNumberWaiting() + "/10)");

					cb.await(); // 调用await方法进行等待，直到等待的线程足够多为止

					// 开始游戏，所有玩家一起进入游戏
					System.out.println("玩家 " + finalI + " 进入游戏！");
				} catch (Exception e) {
					e.printStackTrace();
				}
			});
		}
	}

	// cyclicBarrier.reset();手动重置
	// 已经处于等待状态下的线程，中断并且抛出BrokenBarrierException异常，循环屏障等待线程数归零。
	private static void reset() {
		CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
		for (int i = 0; i < 3; i++) {
			new Thread(() -> {
				try {
					cyclicBarrier.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
			}).start();
		}
		ThreadUtil.sleepMilliSeconds(500);
		System.out.println("当前屏障前线程等待数" + cyclicBarrier.getNumberWaiting());
		cyclicBarrier.reset();
		System.out.println("重置后屏障线程等待数" + cyclicBarrier.getNumberWaiting());
	}

	private static void interrput() {
		CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
		Runnable r = () -> {
			try {
				cyclicBarrier.await();
			} catch (InterruptedException | BrokenBarrierException e) {
				e.printStackTrace();
			}
		};
		Thread t1 = new Thread(r, "thread-1");
		t1.start();
		t1.interrupt();
		new Thread(r, "thread-2").start();
	}

}
